package net.lulihu.common_util.controller_result;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.lulihu.ObjectKit.BeanKit;
import net.lulihu.ObjectKit.ClassKit;
import net.lulihu.ObjectKit.CollectionKit;
import net.lulihu.ObjectKit.StrKit;
import net.lulihu.exception.ExceptionEnum;
import net.lulihu.functional.Consumer;
import net.lulihu.functional.ConsumptionResult;

import java.util.*;

/**
 * 通用返回值设置
 */
@SuppressWarnings("unchecked")
public class Result {

    /**
     * 状态码
     */
    private Integer code;
    /**
     * 状态信息
     */
    private String message;
    /**
     * 数据
     */
    private Object data;

    public Result() {
    }

    public Result(Object data) {
        this(200, "请求成功", data);
    }

    private Result(Integer code, String message) {
        this(code, message, new HashMap<String, Object>());
    }

    private Result(Integer code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * 成功
     */
    public static Result success() {
        return result(200, "请求成功");
    }

    public static Result success(Object data) {
        return result(200, "请求成功", data);
    }

    /**
     * 自定义返回值
     */
    public static Result result(Integer code, String message) {
        return new Result(code, message);
    }

    /**
     * 自定义返回值
     */
    public static Result result(Integer code, String message, Object data) {
        return new Result(code, message, data);
    }

    /**
     * 返回异常错误信息
     */
    public static Result exception(ExceptionEnum ex) {
        return result(ex.getCode(), ex.getMessage());
    }

    /**
     * 返回异常错误信息
     */
    public static Result exception(ExceptionEnum ex, Object data) {
        return result(ex.getCode(), ex.getMessage(), data);
    }

    /**
     * 获取返回值主体参数对象
     *
     * @param clazz 对象类型
     * @param <T>   泛型对象
     * @return 返回指定对象类型的对象
     */
    public <T> T getData(Class<T> clazz) {
        return getObj(data, clazz);
    }

    /**
     * 获取返回值主体参数对象
     *
     * @param clazz 对象类型
     * @param <T>   泛型对象
     * @return 返回指定对象类型的对象
     */
    public <T> List<T> getDataList(Class<T> clazz) {
        return getList(data, clazz);
    }

    /**
     * 获取返回值参数对象
     *
     * @param key   键
     * @param clazz 对象类型
     * @param <T>   泛型对象
     * @return 返回指定对象类型的对象
     */
    public <T> T getObj(String key, Class<T> clazz) {
        if (data == null) return null;
        if (this.data instanceof Map) {
            Object obj = ((Map) this.data).get(key);
            return getObj(obj, clazz);
        }
        throw new IllegalArgumentException("参数主体类型不为Map类型无法通过键获取值");
    }

    private <T> T getObj(Object obj, Class<T> clazz) {
        if (obj == null) return null;
        if (ClassKit.isAssignable(obj.getClass(), clazz)) return (T) obj;
        if (obj instanceof JSONObject) return BeanKit.mapToBean((JSONObject) obj, clazz);
        throw new IllegalArgumentException(StrKit.format("参数类型不匹配【{} != {}】", obj.getClass(), clazz));
    }

    private <T> List<T> getList(Object obj, Class<T> clazz) {
        if (obj == null) return null;
        if (obj instanceof List) {
            List list = (List) obj;
            if (CollectionKit.isEmpty(list)) return new ArrayList<>();
            // 反射封装
            List<T> result = new ArrayList<>();
            for (Object o : list) {
                if (o instanceof JSONObject) {
                    result.add(BeanKit.mapToBean((JSONObject) o, clazz));
                } else
                    throw new IllegalArgumentException(StrKit.format("不支持的json封装对象【{}】", o.getClass()));
            }
            return result;
        }
        throw new IllegalArgumentException(StrKit.format("参数类型不匹配【{} != {}】", obj.getClass(), clazz));
    }


    /**
     * 向返回值主体中添加数据
     * 注意:
     * 该方法只适用于主体数据为Map的数据类型
     *
     * @param key   键
     * @param value 值
     */
    public Result put(String key, Object value) {
        if (this.data == null) this.data = new HashMap<String, Object>();
        if (this.data instanceof Map) {
            ((Map) this.data).put(key, value);
        } else throw new IllegalArgumentException("该方法只限于主体数据为Map的实现类");
        return this;
    }

    /**
     * 使用表达式向返回值主体中添加数据
     *
     * @param consumer 表达式
     */
    public Result put(Consumer<Object> consumer) {
        consumer.accept(this.data);
        return this;
    }

    /**
     * 使用表达式设置返回值主体
     *
     * @param consumer 表达式
     */
    public Result set(ConsumptionResult<Object> consumer) {
        this.data = consumer.accept();
        return this;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }


    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}
